package hebClustering.vectorSpace;

import hebClustering.nlp.Corpus;

import java.util.HashMap;
import java.util.Iterator;

/**
 * An implementation of IVecor.<br>
 * 
 * A vector whose elements are mostly zero, hence only saves those who are not.
 * 
 */
public class SparseVector implements IVector {

	protected HashMap<Integer,Double> nonZeros;
	protected int dimension;
	
	/**
	 * Creates an empty vector.
	 *  
	 * @param dimension - the dimension of the vector.
	 */
	public SparseVector(int dimension){
		this.dimension = dimension;
		nonZeros = new HashMap<Integer, Double>();
	}

	@Override
	public double ithValue(int i) {
		Double res = nonZeros.get(i);
		if (res == null)
			return 0;
		else
			return res;
		
	}

	public void addToVector(int pos, double value) {
		if(value==0){
			if(nonZeros.containsKey(pos))
				nonZeros.remove(pos);
			else return;
		} else
			nonZeros.put(pos, value);
	
	}

	@Override
	public int getDimension() {
		return dimension;
	}

	@Override
	public Iterator<Integer> iterator() {
		return nonZeros.keySet().iterator();
	}

	@Override
	public IVector sub(IVector vec) {
		IVector result = new SparseVector( Math.max(dimension, vec.getDimension()) );
		
		for(int i : this){
			result.addToVector(i, this.ithValue(i));
		}
		
		for(int i : vec){
			result.addToVector(i, result.ithValue(i)-vec.ithValue(i));
		}
		
		return result;
	}
	
	/**
	 * Return a string representation of the non-zero elements only.
	 * 
	 * @return A String representation.
	 */
	public String toString(){
		String output = "(";
		for (int i = 0; i < getDimension(); i++){
			output += ithValue(i) + ",";
		}
		output += ")";
		
		return output;
	}
	
	/**
	 * Prints a string representation of the vector, including the zero elements.
	 */
	public void show(){
		for (int j = 0; j < Corpus.getCorpus().getNumOfTokens(); j++) 
            System.out.printf("%9.4f ", ithValue(j));
		System.out.println();
	}

	@Override
	public double product(IVector vec) {
		double sum = 0;
		for(int i : this){
			sum += this.ithValue(i)*vec.ithValue(i);
		}
		
		return sum;
	}

	@Override
	public boolean equals(IVector vec) {
		IVector diff = sub(vec);
		
		for(int i : diff){
			if(i!=0)
				return false;
		}
		
		return true;
	}

}
